import 'package:dio_cache_interceptor/dio_cache_interceptor.dart';
import 'package:hzy_normal_network/hzy_normal_network.dart';

import 'package:dio/dio.dart' as fdata;

import '../common/index.dart';
import 'dio_cache_tool.dart';

class NetWorkInstance {
  // 私有静态实例
  static final NetWorkInstance _instance = NetWorkInstance._internal();

  /// 工厂构造函数，始终返回同一个实例
  factory NetWorkInstance() {
    return _instance;
  }

  HzyNormalClient? _client;

  /// 私有命名构造函数，防止外部直接实例化
  NetWorkInstance._internal();

  configClient({
    required HzyNormalHttpConfig config,
  }) {
    _client = HzyNormalClient(
      normalHttpConfig: config,
    );
  }

  HzyNormalClient? getClient() {
    if (_client == null) {
      throw Exception("请先配置网络请求");
    }
    return _client;
  }
}

enum Method {
  get,
  post,
}

/*
 * @description: 通用网络请求器
 * @params {
 *            path: 请求接口地址.
 *                  可以是url + path
 *                  也可以 path.但要设置baseurl.才可以正常使用,否者会404.
 *            data: 请求参数
 *          method: 请求方式.默认get
 *  isglobalparams: 是否需要全局参数.默认是true
 *                  这里我简单说一下,什么时候全局参数.一般我们后台接口,会添加一些通用参数.
 *                  比如客户端类型.(iOS,android,h5)等等.这样话,可能就需要大部分接口都
 *                  需要这样的参数.所以为了满足这个需求,我在封装这个请求器的时候,
 *                  就添加了这个参数.
 *    globalparams: 这个就是你要配置全局参数
 *                  你在请求器的方法里写死也可以.或者某些场景需要修改默认参数.这里也是支持的.
 *        showload: 显示默认加载loading.默认是true
 *         loadmsg: 加载动画提示文字.默认 加载中...
 * httpTransformer: 拦截器
 *          policy: 缓存策略
 *                    enum CachePolicy {
                      /// Same as [CachePolicy.request] when origin server has no cache config.
                      ///
                      /// In short, you'll save every successful GET requests.
                      forceCache,

                      /// Same as [CachePolicy.refresh] when origin server has no cache config.
                      refreshForceCache,

                      /// Requests and skips cache save even if
                      /// response has cache directives.
                      noCache,

                      /// Requests regardless cache availability.
                      /// Caches if response has cache directives.
                      refresh,

                      /// Returns the cached value if available (and un-expired).
                      ///
                      /// Checks against origin server otherwise and updates cache freshness
                      /// with returned headers when validation is needed.
                      ///
                      /// Requests otherwise and caches if response has directives.
                      request,
}
 * }
 * @return {网络数据}
 *  
*/
Future<HzyNormalResponse> request({
  required String path,
  dynamic data,
  Method method = Method.get,
  bool isShowLoad = true,
  bool isUpdateCaChe = true,
  bool isShowError = true,
  bool isShowSuccessToast = false,
  bool isNeedGlobalParams = false,
  Map<String, dynamic>? globalparams,
  String loadMsg = "Loading...",
  HzyNormalTransFormer? httpTransformer,
  Options? options,
  CachePolicy policy = CachePolicy.request,
  bool isFormData = false,
}) async {
  HzyNormalResponse res;
  if (isShowLoad) {
    showNormalLoadMsg(msg: loadMsg);
  }
  Map<String, dynamic> params = {};
  if (isNeedGlobalParams) {
    globalparams ??= {};
    params.addAll(globalparams);
  }
  if (data is! fdata.FormData) {
    params.addAll(data ?? {});
  }
  // 缓存配置
  options ??= DioCacheTool.cacheOptions
      ?.copyWith(
        policy: policy,
        keyBuilder: (request) {
          String keyB = data.toString();
          keyB = "$path$keyB";
          return keyB;
        },
      )
      .toOptions();
  // 请求配置
  var client = NetWorkInstance().getClient();
  if (method == Method.get) {
    // get请求
    res = await client!.get(
      url: path,
      queryParameters: params,
      httpTransformer: httpTransformer,
      options: options,
    );
  } else {
    // post请求
    res = await client!.post(
      path,
      data: isFormData ? fdata.FormData.fromMap(data ?? {}) : params,
      httpTransformer: httpTransformer,
      options: options,
    );
  }
  if (isShowLoad) {
    loadDismiss();
  }
  if (isShowError && res.ok == false) {
    // 失败提示
    showToastMsg(
      msg: res.error?.msg ?? "NetWork Fail",
    );
  } else if (res.ok && isShowSuccessToast) {
    // 成功提示
    showToastMsg(
      msg: res.msg,
    );
  }
  if (policy == CachePolicy.forceCache && res.ok && isUpdateCaChe) {
    // 更新缓存
    request(
      path: path,
      data: data,
      isFormData: isFormData,
      method: method,
      isShowLoad: false,
      isShowSuccessToast: false,
      isNeedGlobalParams: isNeedGlobalParams,
      globalparams: globalparams,
      httpTransformer: httpTransformer,
      policy: CachePolicy.refresh,
      isShowError: isShowError,
    );
  }
  return res;
}
